﻿using System;
using System.Collections.Generic;
using System.Reflection;
//using Wizard.Interfaces;
//using Wizard.Runtime;
//using Wizard.Statements;

namespace Wizard.Source
{
    public interface IStatementSource
    {
        //Statement Instantiate(IRunContext runContext);

        IStatementSource AddStatement(string statementType);
    }

    //public class IStatementSource
    //{
    //    private static readonly object[] EmptyArray = new object[] { };
    //    internal StatementInfo mStatementInfo;
    //    internal IBlockSource mParentBlock;
    //    internal string mName;
    //    internal IDictionary<string, BlockVariable> mVariables;
    //    internal IDictionary<string, FieldSource> mFields;
    //    internal IDictionary<string, IBlockSource> mBlocks;

    //    internal IStatementSource()
    //    {
    //        // for MainBlock only
    //        mFields = new Dictionary<string, FieldSource>(StringComparer.OrdinalIgnoreCase);
    //        mBlocks = new Dictionary<string, IBlockSource>(StringComparer.OrdinalIgnoreCase);
    //        mVariables = new Dictionary<string, BlockVariable>(StringComparer.OrdinalIgnoreCase);
    //    }

    //    internal IStatementSource(IBlockSource parentBlock, string type, string name)
    //    {
    //        mFields = new Dictionary<string, FieldSource>(StringComparer.OrdinalIgnoreCase);
    //        mBlocks = new Dictionary<string, IBlockSource>(StringComparer.OrdinalIgnoreCase);
    //        mVariables = new Dictionary<string, BlockVariable>(StringComparer.OrdinalIgnoreCase);

    //        mParentBlock = parentBlock;
    //        // 1st find if the statementtype exists
    //        if (!Source.Engine.StatementInfos.TryGetValue(type, out mStatementInfo))
    //            throw new SourceException(string.Format("Invalid Statement type {0}", type));

    //        // 2nd find if the statementname exists            
    //        var c = Source.GetStatementByName(name);
    //        if (c != null) throw new SourceException(string.Format("Statement name {0} already exists.", type));

    //        mName = name;
    //        //mStatements.Add(this);
    //        // Source.GetStatement(name) = this;
    //        //foreach (var de in mStatementInfo.mStatementFieldInfos)
    //        //{
    //        //    var vi = new VariableSource(de.Value);
    //        //    Statement.AddVariable(vi);
    //        //    mVariables[de.Key] = vi;
    //        //}
    //    }

    //    public virtual IMethodSource Source
    //    {
    //        get { return mParentBlock.Source; }
    //    }

    //    public string Name
    //    {
    //        get { return mName; }
    //    }

    //    public IStatementSource ParentStatement
    //    {
    //        get { return mParentBlock == null ? null : mParentBlock.OwnerStatement; }
    //    }

    //    public IBlockSource Block
    //    {
    //        get { return mParentBlock; }
    //    }

    //    public void SetBlock(string blockName, IBlockSource IBlockSource)
    //    {
    //        BlockFieldInfo fi;
    //        if (mStatementInfo.mInnerBlocks.TryGetValue(blockName, out fi))
    //        {
    //            if (IBlockSource.StatementFieldInfo != null
    //                && IBlockSource.StatementFieldInfo != fi.mFieldInfo)
    //                throw new SourceException(
    //                    string.Format("Cannot set block {0} in Statement {1}, the block is already used somewhere else.",
    //                    blockName,
    //                    mStatementInfo.mStatementName));

    //            IBlockSource.StatementFieldInfo = fi.mFieldInfo;
    //            mBlocks[blockName] = IBlockSource;
    //        }
    //        else
    //        {
    //            throw new SourceException(string.Format("Invalid SetBlock {0} in Statement {1}", blockName,
    //                                                    mStatementInfo.mStatementName));
    //        }
    //    }

    //    public void SetField(string fieldName, object value)
    //    {
    //        StatementFieldInfo fi;
    //        if (mStatementInfo.mStatementFields.TryGetValue(fieldName, out fi))
    //        {
    //            Type ValueType = null;
    //            if (value != null) ValueType = value.GetType();
    //            if (value == null || ValueType == fi.mFieldInfo.FieldType)
    //            {
    //                mFields[fieldName] = new FieldSource(fi.mFieldInfo, value, FieldType.Property);
    //            }
    //            else if (value is IHasValue && ((IHasValue)value).ValueType == fi.mFieldInfo.FieldType)
    //            {
    //                mFields[fieldName] = new FieldSource(fi.mFieldInfo, value, FieldType.IHasValue);
    //            }
    //            else
    //            {
    //                throw new SourceException(string.Format(
    //                                              "Invalid Field type {0} in Statement {1}. Was expecting {2}.",
    //                                              value.GetType().Name, mStatementInfo.mStatementName, fi.mFieldInfo.FieldType.Name));
    //            }
    //        }
    //        else
    //        {
    //            throw new SourceException(string.Format("Invalid Field {0} in Statement {1}", fieldName,
    //                                                    mStatementInfo.mStatementName));
    //        }
    //    }


    //    public void SetDeclVariable(string fieldName, string variableName)
    //    {
    //        LocalVariableFieldInfo lv;
    //        if (mStatementInfo.mLocalVariablesFields.TryGetValue(fieldName, out lv))
    //        {
    //            // c'est bon on tiens la bonne carte
    //            this.mVariables.Add(fieldName, new BlockVariable(lv));
    //            return;
    //        }
    //        throw new SourceException(string.Format("Invalid variable {0} in Statement {1}", fieldName,
    //                                                mStatementInfo.mStatementName));
    //    }

    //    internal Wizard.Statements.Statement Instantiate(IRunContext runContext)
    //    {
    //        var statementInstance = (Statement)mStatementInfo.mConstructorInfo.Invoke(EmptyArray);
    //        foreach (var fi in mFields)
    //        {
    //            if (fi.Value.mType == FieldType.IHasValue)
    //            {
    //                fi.Value.mFieldInfo.SetValue(statementInstance, ((IHasValue)fi.Value.mValue).GetValueObject(runContext));
    //            }
    //            else
    //            {
    //                fi.Value.mFieldInfo.SetValue(statementInstance, fi.Value.mValue);
    //            }
    //        }
    //        if (mStatementInfo.mLocalVariablesFields != null)
    //        {
    //            foreach (var p in mStatementInfo.mLocalVariablesFields)
    //            {
    //                if (p.Value.mConstructorInfo != null)
    //                {
    //                    var variableInstance =
    //                        p.Value.mConstructorInfo.Invoke(new object[] { 
    //                        runContext.ThreadStep.BlockInstance, 
    //                        statementInstance, 
    //                        p.Value });
    //                    p.Value.mFieldInfo.SetValue(statementInstance, variableInstance);
    //                }
    //            }
    //        }

    //        if (mStatementInfo.mInnerBlocks != null)
    //        {
    //            foreach (var p in mBlocks)
    //            {
    //                IBlockSource IBlockSource = p.Value;
    //                IBlockSource.StatementFieldInfo.SetValue(statementInstance, IBlockSource);
    //            }
    //        }

    //        //statementInstance.InstanceInitialize(statementInstance);
    //        return statementInstance;
    //    }

    //}

}